package pl.wwysocki.gendok;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.odftoolkit.odfdom.dom.element.table.TableTableElement;
import org.odftoolkit.odfdom.dom.element.table.TableTableRowElement;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class TableReference
{
	static final Log log = LogFactory.getLog(TableReference.class);
	Node tableParent;
	Node tableDef;
	Node tableRow;
	boolean vertical;
	Map<Object, FieldRef> fields = new HashMap<Object, FieldRef>();

	public TableReference(Node tableDef, Node tableRow)
	{
		super();
		this.tableDef = tableDef;
		this.tableRow = tableRow;
		vertical = (tableDef instanceof TableTableElement)  
			? ((TableTableElement) tableDef).getTableNameAttribute().startsWith("pion")
			: false;
		tableParent = tableDef.getParentNode();
	}

	public Node getTableDef()
	{
		return tableDef;
	}

	public void setTableDef(Node tableDef)
	{
		this.tableDef = tableDef;
	}

	public Node getTableRow()
	{
		return tableRow;
	}

	public void setTableRow(Node tableRow)
	{
		this.tableRow = tableRow;
	}

	public void show()
	{
		log.info(String.format("Tabela %s i jej pola:", ((TableTableElement) tableDef).getTableNameAttribute()));
		for (FieldRef field : fields.values())
		{
			field.show();
		}
	}

	public FieldRef findField(Method getter)
	{
		if (fields.containsKey(getter))
		{
			return fields.get(getter);
		}
		else
		{
			return null;
		}
	}

	public Map<Object, FieldRef> getFields()
	{
		return fields;
	}

	public void addField(FieldRef field)
	{
		fields.put(field.getIdentifier(), field);
	}

	/**
	 * Usunięcie wszystkich wierszy poza nagłowkiem tabeli
	 */
	public void resetTable()
	{
		TableTableElement tDef = (TableTableElement) tableDef;
		if (!vertical)
		{
			NodeList nodes = tDef.getChildNodes();
			Node header = null;
			for (int i = 0; i < nodes.getLength();)
			{
				Node node = nodes.item(i);
				log.info(String.format("Node class %s name %s type %s", node.getClass().getName(), node.getNodeName(),
						node.getNodeType()));
				if (node instanceof TableTableRowElement)
				{
					// omijanie pierwszego wiersza tabeli - nagłówek
					if (header == null)
					{
						header = node;
						i++;
					}
					else
					{
						log.info(String.format("usunieto %s", node.getNodeName()));
						tDef.removeChild(node);
					}
				}
				else
					i++;
			}
		}
		// vertical
		else
		{
			log.info(String.format("Resetowanie pionowej tabeli %s", tDef.getTableNameAttribute()));
			NodeList nodes = tableParent.getChildNodes();
			for (int i = 0; i < nodes.getLength();)
			{
				Node node = nodes.item(i);
				log.info(String.format("Node class %s name %s type %s", node.getClass().getName(), node.getNodeName(),
						node.getNodeType()));
				tableParent.removeChild(node);
			}
		}
	}

	/**
	 * Przygotowanie tabeli do wypełniania danymi - usunięcie wiersza szablonu 
	 */
	public void removeTableRow()
	{
		log.info(String.format("metoda removeTableRow w TableRef %s", ((TableTableElement) tableDef).getTableNameAttribute()));
		for (FieldRef field : getFields().values())
		{
			field.removeTableRow();
		}
		if (!vertical)
		{
			getTableDef().removeChild(getTableRow());
		}
		else
		{
			try
			{
				tableParent.removeChild(tableDef);
			}
			catch (Throwable e)
			{
				String nazwa = (tableDef instanceof TableTableElement)
					? ((TableTableElement) tableDef).getTableNameAttribute()
					: tableDef.getClass().getName(); 
				log.error(String.format("Nie bylo juz tabeli %s wewnatrz %s, blad %s", nazwa, tableParent, e.getMessage()));
			}
		}
	}

	public boolean isVertical()
	{
		return vertical;
	}

	public void setVertical(boolean vertical)
	{
		this.vertical = vertical;
	}

	public void appendNewRow()
	{
		if (!vertical)
		{
			getTableDef().appendChild(tableRow.cloneNode(true));
		}
		else
		{
			tableParent.appendChild(tableDef.cloneNode(true));
		}
	}
}
